﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AutoLoL.Commands;
using AutoLoL.Dialogs;
using AutoLoL.Entities;
using AutoLoL.Logic;
using AutoLoL.Logic.Automation;
using AutoLoL.Logic.Exceptions;
using AutoLoL.Logic.Windows;
using AutoLoL.Shared;

namespace AutoLoL.Controls
{
    /// <summary>
    /// Interaction logic for BuildsControl.xaml
    /// </summary>
    public partial class BuildsControl : UserControl
    {
        private Champion _selectedChampion = null;
        private System.Timers.Timer _filterTimer;
        private List<ChampionBuild> _builds;


        public BuildsControl(List<ChampionBuild> championBuilds)
        {
            InitializeComponent();
            SetChampionBuilds(championBuilds);

            _filterTimer = new System.Timers.Timer(100);
            _filterTimer.Elapsed += new ElapsedEventHandler(FilterTimer_Elapsed);
            _filterTimer.AutoReset = false;
            _filterTimer.Enabled = true;
            _filterTimer.Stop();

            FilterTextBox.Focus();
        }

        public void SetChampionBuilds(List<ChampionBuild> builds)
        {
            builds.Sort((x1, x2) => x1.Title.CompareTo(x2.Title));
            _builds = builds;
            SetFilter();
        }

        private void CreateButton_Click(object sender, RoutedEventArgs e)
        {
            OnRequestCreateBuild(new RequestCreateBuildArgs(_selectedChampion));
        }

        private void EditButton_Click(object sender, RoutedEventArgs e)
        {
            EditSelected();
        }

        private void BuildsDataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            EditSelected();
        }

        private void MenuItemEdit_Click(object sender, RoutedEventArgs e)
        {
            EditSelected();
        }

        private void MenuItemDeploy_Click(object sender, RoutedEventArgs e)
        {
            DeploySelected();
        }

        private void DeploySelected()
        {
            //setup some variables to handle multiple builds for the same champion
            string lastChampion = string.Empty;
            GameType lastGameType = GameType.Classic;
            int setNumber = 1;

            //Loop through all our selected items ordering by the champion name and then the game type to handle multiple builds for the same champion and same game type
            foreach (ChampionBuild championBuild in BuildsDataGrid.SelectedItems.OfType<ChampionBuild>().OrderBy(x => x.Champion.DirectoryName).ThenBy(x => x.GameType))
            {
                //If we have a new champion
                if (lastChampion == string.Empty || (lastChampion != championBuild.Champion.DirectoryName || lastGameType != championBuild.GameType))
                {
                    //Done adding all the sets for the last champion so deploy it
                    if (setNumber > 1)
                    {
                        AutoDeploy.Deploy();
                    }

                    //Reset the set number since we are a new champion
                    setNumber = 1;

                    //Read in whatever we had before for this champion
                    AutoDeploy.readFromFile(championBuild.Champion.DirectoryName, championBuild.GameType);

                    //Add the current set
                    AutoDeploy.addSet(championBuild.Champion.DirectoryName, championBuild.GameType, championBuild.Items, setNumber, championBuild.Title);

                    //Update our values
                    setNumber++;
                    lastChampion = championBuild.Champion.DirectoryName;
                }
                else
                {
                    int tempSetNumber = setNumber;

                    //Promt the user about setting this one as the first set (default items) instead
                    MessageBoxResult result = MessageBox.Show("Detected another " + championBuild.GameType + " build for " + championBuild.Champion.Name + ". Would you like " + championBuild.Title + " to be the default set instead?", "Yes or no?", MessageBoxButton.YesNo);

                    if (result == MessageBoxResult.Yes)
                        tempSetNumber = 1;
                    
                    //Add another set for the same champion
                    AutoDeploy.addSet(championBuild.Champion.DirectoryName, championBuild.GameType, championBuild.Items, tempSetNumber, championBuild.Title);

                    //Update our values
                    setNumber++;
                }
            }

            //Done adding all the sets for the last champion so deploy it
            if (setNumber > 1)
            {
                AutoDeploy.Deploy();
            }

            MessageBox.Show("Deployed (set) default items for the selected champions.");
        }

        private void EditSelected()
        {
            ChampionBuild championBuild = BuildsDataGrid.SelectedItems.OfType<ChampionBuild>().FirstOrDefault();
            if (championBuild != null)
            {
                OnRequestEditBuild(new RequestEditBuildArgs(championBuild));
            }
        }

        private void MenuItemDelete_Click(object sender, RoutedEventArgs e)
        {
            ConfirmDialog dialog = new ConfirmDialog(Window.GetWindow(this), "Are you sure you want to delete the selected build(s)?");
            dialog.ShowDialog();
            if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
            {
                foreach (ChampionBuild championBuild in BuildsDataGrid.SelectedItems.OfType<ChampionBuild>())
                {
                    OnRequestDeleteBuilds(new RequestDeleteBuildsArgs(championBuild));
                }
            }
        }

        private void SetFilter()
        {
            IEnumerable<ChampionBuild> builds = _builds;

            // Filter champions
            if (_selectedChampion != null)
            {
                builds = builds.Where(c => _selectedChampion == c.Champion);
            }

            // Filter text
            string[] filters = FilterTextBox.Text.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            if (filters.Length > 0)
            {
                builds = builds.Where(c => IsFilterInTitle(filters, c.Title));
            }

            BuildsDataGrid.Columns[1].SortDirection = ListSortDirection.Ascending;
            BuildsDataGrid.ItemsSource = builds;
        }

        private bool IsFilterInTitle(string[] filters, string title)
        {
            foreach (string filter in filters)
            {
                if (!string.IsNullOrEmpty(filter))
                {
                    if (title.ToLower().Contains(filter.ToLower()))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private void ChampionGrid_MouseDown(object sender, MouseButtonEventArgs e)
        {
            List<Champion> selectedChampion = null;
            if (_selectedChampion != null)
            {
                selectedChampion = new List<Champion>() { _selectedChampion };
            }

            ChampionDialog dialog = new ChampionDialog(Window.GetWindow(this), selectedChampion, false, true);
            dialog.ShowDialog();

            if (dialog.SelectedChampions != null)
            {
                if (dialog.SelectedChampions.Count > 0)
                {
                    _selectedChampion = dialog.SelectedChampions[0];
                    ChampionImage.Source = _selectedChampion.IconBitmapImage;
                }
                else
                {
                    _selectedChampion = null;
                    ChampionImage.Source = null;
                }
            }

            SetFilter();
        }

        private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                SetFilter();
            }
        }

        private void FilterTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Dispatcher.BeginInvoke((ThreadStart)(() =>
            {
                SetFilter();
            }));
        }

        private void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            _filterTimer.Stop();
            _filterTimer.Start();
        }

        public event RequestCreateBuild RequestCreateBuild;
        protected virtual void OnRequestCreateBuild(RequestCreateBuildArgs e)
        {
            if (RequestCreateBuild != null)
            {
                RequestCreateBuild(this, e);
            }
        }

        public event RequestEditBuild RequestEditBuild;
        protected virtual void OnRequestEditBuild(RequestEditBuildArgs e)
        {
            if (RequestEditBuild != null)
            {
                RequestEditBuild(this, e);
            }
        }

        public event RequestDeleteBuilds RequestDeleteBuild;
        protected virtual void OnRequestDeleteBuilds(RequestDeleteBuildsArgs e)
        {
            if (RequestDeleteBuild != null)
            {
                RequestDeleteBuild(this, e);
            }
        }

        private void QuickPlay_Click(object sender, RoutedEventArgs e)
        {

            
            try
            {
                MASTERY_WINDOWS targetWindow = MASTERY_WINDOWS.None;

                while (true)
                {
                    try
                    {
                        AutoClicker.Click((BuildsDataGrid.SelectedItem as ChampionBuild).MasteryBuild, targetWindow, UserSettings.Instance.IsManualReturnEnabled);
                    }
                    catch (MasteriesNotDetectedException ex2)
                    {
                        Window.GetWindow(this).Activate();

                        SelectWindowDialog dialog = new SelectWindowDialog();
                        dialog.ShowDialog();

                        if (dialog.MasteryWindow != null)
                        {
                            targetWindow = dialog.MasteryWindow.Value;
                            continue; // Restart the loop
                        }
                        else
                        {
                            break;
                        }
                    }

                    break;
                }
            }
            catch (Exception ex1)
            {
                Window.GetWindow(this).Activate();

                string message = ex1.Message;
                ConfirmDialog dialog = new ConfirmDialog(Window.GetWindow(this), message, "Error", false);
                dialog.ShowDialog();
            }
        }
    }

    public delegate void RequestCreateBuild(object sender, RequestCreateBuildArgs e);
    public class RequestCreateBuildArgs : System.EventArgs
    {
        public RequestCreateBuildArgs(Champion champion = null)
        {
            this.Champion = champion;
        }

        public Champion Champion { get; private set; }
    }

    public delegate void RequestEditBuild(object sender, RequestEditBuildArgs e);
    public class RequestEditBuildArgs : System.EventArgs
    {
        public RequestEditBuildArgs(ChampionBuild championBuild)
        {
            this.ChampionBuild = championBuild;
        }

        public ChampionBuild ChampionBuild { get; private set; }
    }

    public delegate void RequestDeleteBuilds(object sender, RequestDeleteBuildsArgs e);
    public class RequestDeleteBuildsArgs : System.EventArgs
    {
        public RequestDeleteBuildsArgs(ChampionBuild championBuild)
        {
            this.ChampionBuild = championBuild;
        }

        public ChampionBuild ChampionBuild { get; private set; }
    }
}